package com.lmq.service.impl.utils;

import com.lmq.utils.BotInterface;
import org.joor.Reflect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.UUID;

@Component
public class Consumer extends Thread {

    private Bot bot;

    private static RestTemplate restTemplate;
    private static final String url = "http://127.0.0.1:8999/pk/bot/receive/";

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        Consumer.restTemplate = restTemplate;
    }

    public void startTimeout(long timeout, Bot bot) {
        this.bot = bot;
        this.start();
        try {
            this.join(timeout);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            this.interrupt();
        }
    }

    private String addUid(String code, String uid) {
        int k = code.indexOf(" implements com.lmq.utils.BotInterface");
        return code.substring(0, k) + uid + code.substring(k);
    }

    private String codeInit = "package com.lmq.utils;\n" +
            "\n" +
            "import com.alibaba.fastjson.JSONObject;\n" +
            "\n" +
            "import java.util.*;\n" +
            "\n" +
            "public class Bot implements com.lmq.utils.BotInterface {\n" +
            "\n" +
            "    static class Cell {\n" +
            "        public int x, y;\n" +
            "        public Cell(int x, int y) {\n" +
            "            this.x = x;\n" +
            "            this.y = y;\n" +
            "        }\n" +
            "    }\n" +
            "    private int[][] g;\n" +
            "    private Integer asx, asy, bsx, bsy;\n" +
            "    private String aSteps;\n" +
            "    private String bSteps;\n" +
            "    private List<Cell> aCells;\n" +
            "    private List<Cell> bCells;\n" +
            "    int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};\n" +
            "\n" +
            "    private boolean check_tail_increasing(int step) {\n" +
            "        if (step <= 10) return true;\n" +
            "        return step % 3 == 1;\n" +
            "    }\n" +
            "\n" +
            "    public List<Cell> getCells(int sx, int sy, String steps) {\n" +
            "        List<Cell> res = new ArrayList<>();\n" +
            "\n" +
            "        int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};\n" +
            "        int x = sx, y = sy;\n" +
            "        int step = 0;\n" +
            "        res.add(new Cell(x, y));\n" +
            "        for(int i = 0; i < steps.length(); i ++ ) {\n" +
            "            int d = steps.charAt(i) - '0';\n" +
            "            x += dx[d];\n" +
            "            y += dy[d];\n" +
            "            res.add(new Cell(x, y));\n" +
            "            if(!check_tail_increasing( ++ step)) {\n" +
            "                res.remove(0);\n" +
            "            }\n" +
            "        }\n" +
            "        return res;\n" +
            "    }\n" +
            "\n" +
            "    public void getData(String input) {\n" +
            "        JSONObject msg = JSONObject.parseObject(input);\n" +
            "        String map = msg.get(\"map\").toString();\n" +
            "        Integer asx = (Integer) msg.get(\"me_sx\");\n" +
            "        Integer asy = (Integer) msg.get(\"me_sy\");\n" +
            "        String aSteps = msg.get(\"me_steps\").toString();\n" +
            "\n" +
            "        Integer bsx = (Integer) msg.get(\"me_sx\");\n" +
            "        Integer bsy = (Integer) msg.get(\"me_sy\");\n" +
            "        String bSteps = msg.get(\"me_steps\").toString();\n" +
            "\n" +
            "        this.g = new int[13][14];\n" +
            "        for(int i = 0, k = 0; i < 13; i++) {\n" +
            "            for(int j = 0; j < 14; j++, k++) {\n" +
            "                if(map.charAt(k) == '1') {\n" +
            "                    g[i][j] = 1;\n" +
            "                }\n" +
            "            }\n" +
            "        }\n" +
            "\n" +
            "        this.asx = asx;\n" +
            "        this.asy = asy;\n" +
            "        this.bsx = bsx;\n" +
            "        this.bsy = bsy;\n" +
            "\n" +
            "        this.aCells = getCells(asx, asy, aSteps);\n" +
            "        this.bCells = getCells(bsx, bsy, bSteps);\n" +
            "    }";

    @Override
    public void run() {
        UUID uuid = UUID.randomUUID();
        String uid = uuid.toString().substring(0, 8);

        BotInterface botInterface = Reflect.compile(
                "com.lmq.utils.Bot" + uid,
                addUid(codeInit, uid) + bot.getBotCode() + "}"
        ).create().get();

        Integer res = botInterface.nextMove(bot.getInput());
        System.out.println(bot.getUserId() + " " + res);

        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("userId", bot.getUserId().toString());
        data.add("direction", res.toString());

        restTemplate.postForObject(url, data, String.class);
    }
}
